#ifndef __DRV_L1_USBH_H__
#define __DRV_L1_USBH_H__
#include "project.h"

#ifndef max
#define max(a, b)	(((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a, b)	(((a) < (b)) ? (a) : (b))
#endif
#define OUT_TOKEN					(0x00 << 8)
#define IN_TOKEN					(0x01 << 8)
#define SETUP_TOKEN					(0x02 << 8)
#define OUT_MAX_PKT					1024
#define IN_MAX_PKT					1024
#define TIMEOUT_RETRY				100
#define MAX_NAK_CNT					600000

#define USBDH_OPERATION_FUN_MAX_NUM 6

#define USBH_EHCI_TYPE	0
#define USBH_OHCI_TYPE	1
#define USBH_TYPE		USBH_EHCI_TYPE

/* USBH error code define */
#define USBH_E_NoErr	0x00
#define USBH_E_RX		0x01
#define USBH_E_TX		0x02
#define USBH_E_NACK		0x03
#define USBH_E_Stall	0x04
#define USBH_E_UnPID	0x05
#define USBH_E_BitStuff 0x06
#define USBH_E_DataSeq	0x07
#define USBH_E_CRC16	0x08
#define USBH_E_TimeOut	0x09
#define USBH_E_Para		0x0A
#define USBH_E_DMA		0x10
#define USBH_E_Remove	0xFF

/********************* Define rUHCtrl bit mask (Offset + 0x04) *****************/
#define MASK_UH_CTRL_MASTER_EN	BIT0	/* USB host AHB master enable */

typedef enum
{
	EP_CONTROL_TYPE		= 0,
	EP_BULK_TYPE,
	EP_ISO_TYPE,
	EP_INTERRUPT_TYPE
} EP_TYPE;

typedef struct
{
	INT8U	cAddr;						// USB address
	INT8U	cEndp;						// USB endpoint
	INT8U	cDMAeEn;					// DMA enable
	INT8U	cEPType;					// EndPoint Type
	INT32U	uiLn;						// buffer length
	INT32U	uiMaxPkt;					// maximum packet size
	INT32U	*pAct;						// active length
	INT32U	*offset;					// Buffer offset (for DMA use)
	INT8U	*cTog;						// USB data toggle
	INT8U	*pErrorCode;
	void	*pBuf;						// data buffer address
} ST_USBH_CTRL;

typedef struct _USBH_OPERATION_TBL
{
	void (*host_init) (void);
	void (*host_uninit) (void);
	INT32U (*host_detect_port) (void);
	INT32U (*issue_setup) (ST_USBH_CTRL * Ctrl);
	INT32U (*issue_in_token) (ST_USBH_CTRL * Ctrl);
	INT32U (*issue_out_token) (ST_USBH_CTRL * Ctrl);
	INT32U (*get_sof_frame_num) (void);
	INT32U (*wait_interrupt) (INT32U uiPollBit);
	void (*wait_sof_tick) (INT32U nSOF);
	void (*issue_hw_reset) (INT32U uiTick);
}

USBH_OPERATION_TBL;

typedef struct USB_HOST_COMMON_REGS_S
{
	volatile INT32U rUHVersion;			/*offset 0x00 */
	volatile INT32U rUHCtrl;			/*offset 0x04 */
	volatile INT32U dummy[2];			/* dummy 8 bytes */
	volatile INT32U rUHPort1PowerCtrl;	/*offset 0x10 */
	volatile INT32U rUHPort2PowerCtrl;	/*offset 0x14 */
} USB_HOST_COMMON_REGS_T;

extern void		drv_l1_usbh_init(void);
extern void		drv_l1_usbh_uninit(void);
extern INT32U	drv_l1_usbh_detect_port(void);
extern INT32U	drv_l1_usbh_issue_setup(ST_USBH_CTRL *Ctrl);
extern INT32U	drv_l1_usbh_in_token(ST_USBH_CTRL *Ctrl);
extern INT32U	drv_l1_usbh_out_token(ST_USBH_CTRL *Ctrl);
extern INT32U	drv_l1_usbh_get_sof_frame_num(void);
extern INT32U	drv_l1_usbh_wait_int(INT32U poll_bit);
extern void		drv_l1_usbh_wait_sof_tick(INT32U sofnum);
extern void		drv_l1_usbh_issue_reset(INT32U tick);
extern void		drv_l1_usbh_register_host_operation_table(USBH_OPERATION_TBL *op_tbl);
extern void		drv_l1_usbh_phy_clk_on(void);
extern void		drv_l1_usbh_phy_clk_off(void);
extern void		drv_l1_usbd_phy_config(INT32U idx);
#endif /*__DRV_L1_USBH_H__*/
